package com.second.app.thread.线程基础.day04.suochongru;


/**
 * @Author GYZ
 * @Date 2023/11/22
 * <pre>
 *   案例：锁重入：可重入锁的概念：自己可以再次获取自己内部的锁、
 *        比如有1个线程获取对象锁，此时这对象锁没有释放，当其再次想要获取这个对象的锁的时候
 *        还是可以获取的，如果不可以锁重入的话，就会造成死锁。
 *
 *    案例1：比如有1个线程获取对象锁，此时这对象锁没有释放，当其再次想要获取这个对象的锁的时候
 *    案例2：当父子类存在继承关系时，子类完全可以通过"可重入锁"调用父类的同步方法。
 *    案例3：出现异常，锁自动释放。比如线程a执行过程中出现异常，
 *           但是另外一个线程，还是可以正常进入同步方法执行。
 *    案例4：同步不具有继承性
 *            线程a调用serviceMethod方法，再调用父类serviceMethod()方法，父类中serviceMethod方法，为同步方法
 *            我们是想验证既然是同步方法，那么b线程，必须等a线程执行完成才可以子类serviceMethod方法，其实不然。
 *            所以证明了同步不能继承。
 *
 *            如果想要同步，需要在子类serviceMethod()方法中，加上synchronized关键字
 *
 *
 *   * </pre>
 */
//案例4
class MainDemo {
    synchronized public void serviceMethod() {
        try {
            System.out.println("int main 下一步 sleep begin threadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("int main 下一步 sleep end threadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class SubDemo extends MainDemo {
    @Override
    synchronized public  void serviceMethod() {
        try {
            System.out.println("int sub 下一步 sleep begin threadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("int sub 下一步 sleep end threadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis());
            super.serviceMethod();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
//案例4

class TestFour {
    public static void main(String[] args) {

        class HsiThread001 extends Thread {
            private SubDemo subDemo;

            public HsiThread001(SubDemo subDemo) {
                this.subDemo = subDemo;
            }

            @Override
            public void run() {
                subDemo.serviceMethod();
            }
        }

        class HsiThread002 extends Thread {
            private SubDemo subDemo;

            public HsiThread002(SubDemo subDemo) {
                this.subDemo = subDemo;
            }

            @Override
            public void run() {
                subDemo.serviceMethod();
            }
        }
        SubDemo subDemo = new SubDemo();

        HsiThread001 hsiThread001 = new HsiThread001(subDemo);
        hsiThread001.setName("A");
        hsiThread001.start();

        HsiThread002 hsiThread002 = new HsiThread002(subDemo);
        hsiThread002.setName("B");
        hsiThread002.start();
    }
}


//案例3
class Service3 {

    synchronized public void testMethod() {
        if (Thread.currentThread().getName().equals("a")) {
            System.out.println("ThreadName=" + Thread.currentThread().getName() + " run beginTime=" + System.currentTimeMillis());
            int i = 1;
            while (i == 1) {
                if (("" + Math.random()).substring(0, 8).equals("0.123456")) {
                    System.out.println("ThreadName=" + Thread.currentThread().getName() + " run exceptionTime=" + System.currentTimeMillis());
                    Integer.parseInt("a");
                }
            }
        } else {
            System.out.println("Thread B run Time=" + System.currentTimeMillis());
        }
    }
}

//案例3
class TestService3 {
    public static void main(String[] args) {
        class Thread003 extends Thread {
            private Service3 service3;

            public Thread003(Service3 service3) {
                this.service3 = service3;
            }

            @Override
            public void run() {
                service3.testMethod();
            }
        }

        class Thread004 extends Thread {
            private Service3 service3;

            public Thread004(Service3 service3) {
                this.service3 = service3;
            }

            @Override
            public void run() {
                service3.testMethod();
            }
        }
        try {
            Service3 service3 = new Service3();
            Thread003 thread003 = new Thread003(service3);
            thread003.setName("a");
            thread003.start();
            Thread.sleep(500);
            Thread004 thread004 = new Thread004(service3);
            thread004.setName("b");
            thread004.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


//案例1
public class Service {
    synchronized public void service1() {
        System.out.println("service1");
        service2();
    }

    synchronized public void service2() {
        System.out.println("service2");
        service3();
    }

    synchronized public void service3() {
        System.out.println("service3");
    }
}

//案例2
class Main {
    public int i = 10;

    synchronized public void operateIMainMethod() {
        try {
            i--;
            System.out.println("main print i=" + i);
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

//案例2
class Sub extends Main {
    synchronized public void operateISubMethod() {
        try {
            while (i > 0) {
                i--;
                System.out.println("sub print i=" + i);
                Thread.sleep(100);
                operateIMainMethod();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

//案例2
class Test001 {
    public static void main(String[] args) {
        class Thread002 extends Thread {

            private Sub sub;

            public Thread002(Sub sub) {
                this.sub = sub;
            }

            @Override
            public void run() {
                sub.operateISubMethod();
            }
        }

        Sub sub = new Sub();
        new Thread002(sub).start();
    }
}

//案例1
class Test {
    public static void main(String[] args) {
        class MyThread extends Thread {
            private Service service;

            public MyThread(Service service) {
                this.service = service;
            }

            @Override
            public void run() {
                service.service1();
            }
        }
        Service service = new Service();
        MyThread myThread = new MyThread(service);
        myThread.start();
    }
}
